<?php
/**
 * DMFramework
 * 
 * @license Copyright 2012 Dillen Meijboom under the Apache license version 2.0 (http://apache.org/licenses/LICENSE-2.0)
 * @author Dillen Meijboom <info@dillenm.nl>
 * @url http://dmframework.nl
 */

/**
 * The table-iterator can be used to iterate over database-tables.
 * 
 * @license Copyright 2012 Dillen Meijboom under the Apache license version 2.0 (http://apache.org/licenses/LICENSE-2.0)
 * @author Dillen Meijboom <info@dillenm.nl>
 * @package System.Library.Database.Table
 */
class Dmf_Database_Table_Iterator
{
    /**
     * All filters
     * 
     * @var array
     */
    private $_filters = array();
    
    /**
     * Limit from
     * 
     * @var int
     */
    private $_from;
    
    /**
     * Limit to
     * 
     * @var int
     */
    private $_to;
    
    /**
     * Table and connection information
     * 
     * @var array
     */
    private $_conInfo = array();
    
    /**
     * All iterated results
     * 
     * @var array
     */
    private $_results = array();
    
    /**
     * Sort result by this index
     *  
     * @var string
     */
    private $_sort;
    
    /**
     * Table object
     * 
     * @var Dmf_Database_Table
     */
    private $_table;
    
    /**
     * Tablename
     * 
     * @var string 
     */
    private $_name;
    
    /**
     * Sort mode
     * 
     * @var string 
     */
    private $_sortMode;
    
    /**
     * Like statements
     * 
     * @var array
     */
    private $_likes = array();
    
    /**
     * Custom query
     * 
     * @var string
     */
    private $_query;
    
    /**
     * All values
     * 
     * @var array
     */
    private $_values = array();
    
    /**
     * Get table object withouth the "Table" prefix!
     * 
     * @param string $table
     * @return Dmf_Database_Table_Iterator 
     */
    public function getTable( $table )
    {
        $class = ( strstr( $table, 'Model' ) ? $table : $table . 'Model' );
        $obj = new $class( false );
        
        $this->_conInfo = $obj->getInfo();
        $this->_table = $obj;
        $this->_name = substr( $class, 0, -5 );
        
        return $this;
    }
    
    /**
     * Get the correct database adapter with the info
     * 
     * @return Dmf_Database_Adapter 
     */
    public function getDatabaseAdapter()
    {
        return $this->_table->getDb();
    }
    
    /**
     * Add text to query
     * 
     * @param string $query
     * @param array $values 
     */
    public function addQuery( $query, $values = array() )
    {
        $this->_query .= ' ' . $query . ' ';
        
        foreach( $values as $val )
        {
            $this->_values[] = $val;
        }
        
        return $this;
    }
    
    /**
     * Get information
     * 
     * @return array
     */
    public function getInfo()
    {
        return $this->_conInfo;
    }
    
    /**
     * Filter the upcoming result
     * 
     * @param string $index
     * @param string $value
     * @return Dmf_Database_Table_Iterator 
     */
    public function filter( $index, $value = null )
    {
        if ( is_array( $index ) )
        {
            foreach( $index as $key => $val )
            {
                $this->filter( $key, $val );
            }
        }
        else
        {
            $this->_filters[ $index ] = $value;
        }
        
        return $this;
    }
    
    /**
     * Sort the upcoming result
     * 
     * @param string $index
     * @param boolean $asc
     * @return Dmf_Database_Table_Iterator 
     */
    public function sort( $index, $asc = true )
    {
        $this->_sort = $index;
        $this->_sortMode = ( $asc === true ? 'ASC' : 'DESC' );
        
        return $this;
    }
    
    /**
     * Limit the upcoming result
     * 
     * @param int $from
     * @param int $to
     * @return Dmf_Database_Table_Iterator 
     */
    public function limit( $from, $to = false )
    {
        $this->_from = $from;
        $this->_to = $to;
        
        if ( $to === false )
        {
            $this->_from = 0;
            $this->_to = $from;
        }
        
        return $this;
    }
    
    /**
     * Search
     * 
     * @param string $index
     * @param string $value
     * @return Dmf_Database_Table_Iterator 
     */
    public function search( $index, $value = false )
    {        
        if ( is_array( $index ) )
        {
            foreach( $index as $key => $val )
            {
                $this->search( $key, $val );
            }
        }
        else
        {
            $this->_likes[ $index ] = $value;
        }
        
        return $this;
    }
    
    /**
     * Execute a query and return result
     * 
     * @param boolean $keepSettings
     * @return Dmf_Database_Table_Iterator 
     */
    public function execute( $keepSettings = false )
    {
        $query = 'SELECT `' . $this->_conInfo['id_column'] . '` FROM `' . $this->_conInfo['table'] . '`';
        $values = array();
            
        if ( count( $this->_filters ) > 0 || count( $this->_likes ) > 0 )
        {
            $where = '';

            foreach( $this->_filters as $column => $value )
            {
                $values[] = $value;
                $where .= ' AND `' . $column . '`=?';
            }
            
            foreach( $this->_likes as $column => $value )
            {
                $values[] = $value;
                $where .= ' AND `' . $column . '` LIKE ?';
            }

            $query .= ' WHERE' . substr( $where, 4 );
        }
        
        $query .= $this->_query;
        
        foreach( $this->_values as $val )
        {
            $values[] = $val;
        }
        
        if ( $this->_sort !== null )
        {
            $query .= ' ORDER BY `' . $this->_sort . '` ' . $this->_sortMode;
        }
        
        if ( $this->_from !== null && $this->_to !== null )
        {
            if ( $this->_from > $this->_to )
            {
                throw new Dmf_Exception_Mysql( 'In database-table iterator from limit can not be higher then the to limit.' );
            }
            
            $query .= ' LIMIT ' . $this->_from . ', ' . ( $this->_to - $this->_from );
        }
        
        $tables = array();
        
        if ( ! isset( $value ) && count( $values ) == 0 || isset( $values ) && count( $values ) == 0 )
        {
            $rows = $this->_table->getDb()->fetchAll( $query );
        }
        else
        {
            $rows = $this->_table->getDb()->fetchAll( $query, $values );
        }
        
        foreach( $rows as $row )
        {
            $class = $this->_name . 'Model';
            $tables[] = new $class( $row[ $this->_conInfo['id_column'] ] );
        }
        
        $this->_results[] = new Dmf_Database_Table_Iterator_Results( $tables );
        
        if ( $keepSettings === false )
        {
            $this->_filters = array();
            $this->_from = null;
            $this->_to = null;
            $this->_sortMode = null;
        }
        
        return $this;
    }
    
    /**
     * Get all results
     * 
     * @return array
     */
    public function getResults()
    {
        return $this->_results;
    }
    
    /**
     * Get the last result
     * 
     * @param bool $andExecute
     * @return array 
     */
    public function getResult( $andExecute = false )
    {
        if ( $andExecute )
        {
            $this->execute();
        }
        
        return end( $this->_results );
    }
}